/* Autostop
 *
 * Copyright (c) Maciej Gajewski, Grzegorz Latarowski
 * http://code.google.com/p/autostop-automaty-drogowe
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
 */

/// @file ff.c Simple writer/reader through FPGA's fifo into slave processor serial

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "registers.h"
#include "tools.h"


// =============
// constants
const int timeout 	= 100;	// timeout waiting for response [ms] 
const int interval	= 10;	// polling interval [ms]
const int fiford	= 1;	// read fifo register addr
const int fifowr	= CWR_FF;	// write fifo register addr
const char* endline = "\r";	// endline send at the end

// ============================================================================
// usage info
static void usage()
{
	tools_usage();
	fprintf( stderr, "ff - read/wrtie throutgh FIFO\n");
	fprintf( stderr, "usage: ff <command> [command [command [...]]]\n");
	fprintf( stderr, "    Command is send through fifo, terminated with endline.\n");
	fprintf( stderr, "    Response is read unitl %.2lf sec idle\n", timeout / 1000.0 );
}

// ============================================================================
// data avilable
/// Returns non-zero if there is data avilable in fifo for reading
///\arg device device handler
#define data_available( device ) ( read_register( device, 0 ) & 8 )
// ============================================================================
// fifo full
/// Returns non-zero if fifo is full
///\arg device device handler
#define fifo_full( device ) ( read_register( device, 0 ) & 4 )

// ============================================================================
// write string
/// Writes string to fifo
void write_string( int device, const char* c )
{
	while ( *c )
	{
		write_register( device, fifowr, *c );
		c++;
		// TODO check fullxp here, when writing over 60 bytes
	}
}

// ============================================================================
// main
int main( int argc, char** argv )
{
	int device = -1;
	int waiting	= 0;	// waiting time [ms]
	int arg;			// index
	
	// check params
	if ( argc < 2 ) {
		usage();
		return 2;
	}
	
	// open default device file
	device = open( TOOLS_DEFAULT_DEVICE, O_RDONLY );
	if ( device < 0 ) {
		perror( "could not open " TOOLS_DEFAULT_DEVICE );
		return 1;
	}
	
	// write args to fifo
	for ( arg = 1; arg < argc; arg++ )
	{
		write_string( device, argv[arg] );
		// write space (separator)
		if ( arg < argc-1 )
		{
			write_register( device, fifowr, ' ' );
		}
	}
	// wrtie endline
	write_string( device, endline );
	
	// wait for response
	while( waiting < timeout )
	{
		// read while data available
		while ( data_available( device ) )
		{
			// read
			int c = 0;
			c = read_register( device, fiford );
			// put onto screen
			putchar(c);
			// reset timeout timer
			waiting = 0;
		}
		// wait for more data
		usleep( interval * 1000 );
		waiting += interval;
	}
	
	// print endline to get nice prompt
	printf("\n");
	
	// happy end
	return 0;
}

// eof

